package titan.wizards.newBasedComponent;

import java.io.File;
import java.net.URL;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import titan.data.components.ComponentData;
import titan.data.components.ComponentList;
import titan.messages.Messages;
import titan.utils.FileUtils;
import titan.utils.SWTUtils;
import titan.utils.TitanUtils;
import titan.wizards.BaseTitanPage;

/**
 * At this page, you can select the component to base your new component and
 * choose which engines will be copied to the new component
 */
public class ComponentPage extends BaseTitanPage {
	private Combo componentCombo;
	private Text unixName;
	private Button[] engineChecks;
	private ComponentList compList;
	private int maxEngines;
	private Button infoButton;
	private String componentDoc;
	private IProject project;
	private String localCompPath;
	//Status
	private IStatus unixNameStatus;

	public ComponentPage() {
		super(Messages.NewComponent);
		setTitle(Messages.NewComponent);
		setDescription(Messages.ComponentPage_desc);
		unixNameStatus = pageStatus = new Status(IStatus.OK, "default", ""); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * {@inheritDoc}
	 */
	public void createControl(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout(4, false);
		layout.verticalSpacing = 6;
		composite.setLayout(layout);
		setControl(composite);
		GridData gd = new GridData(320, 13);

		MouseTrackAdapter mouseExit = new MouseTrackAdapter() {
			public void mouseExit(MouseEvent e) {
			    applyStatus(pageStatus);
			}
		};

		new Label(composite, SWT.NONE).setText(Messages.Component+":"); //$NON-NLS-1$
		componentCombo = new Combo (composite, SWT.READ_ONLY);
		gd.horizontalSpan = 2;
		gd.horizontalAlignment = SWT.FILL;
		componentCombo.setLayoutData(gd);
		for(int i = 0; i < compList.getSize(); i++)
			componentCombo.add(compList.getComponent(i).getName());
		componentCombo.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				componentChanged();
			}
		});
		componentCombo.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "componentCombo", Messages.SelectComponent) ); //$NON-NLS-1$
			}
		});
		componentCombo.addMouseTrackListener(mouseExit);

	    infoButton = new Button(composite, SWT.PUSH);
		try {
			URL imageUrl = FileLocator.toFileURL( getClass().getResource("/resources/icons/info.png")); //$NON-NLS-1$
			Image image = new Image(null, imageUrl.getPath());
		    infoButton.setImage(image);
		} catch (Exception e) {
			infoButton.setText("info"); //$NON-NLS-1$
		}
		infoButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				SWTUtils.openContentDialog(getShell(), Messages.ComponentInfo, componentDoc);
			}
		});

		new Label(composite, SWT.NONE).setText(Messages.UnixName+":"); //$NON-NLS-1$
		unixName = new Text(composite, SWT.BORDER | SWT.SINGLE);
		gd = new GridData();
		gd.horizontalSpan = 2;
		gd.horizontalAlignment = SWT.FILL;
		unixName.setLayoutData(gd);
		unixName.setText(compList.getComponent(0).getName());
		unixName.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				Status status = new Status(IStatus.OK, "projectName", ""); //$NON-NLS-1$ //$NON-NLS-2$
				try {
					if(!FileUtils.isEmptyFolder(localCompPath+unixName.getText()))
						status = new Status(IStatus.WARNING, "unixName", //$NON-NLS-1$
								Messages.CompFolderNEmpty+Messages.ContentWillBeReplaced);
				} catch (Exception e) {
					status = new Status(IStatus.ERROR, "unixName", e.getMessage()); //$NON-NLS-1$
				}
				applyStatus(status);
			}
		});
		unixName.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
				applyStatus(new Status(IStatus.INFO, "packageName", Messages.ComponentName_desc) ); //$NON-NLS-1$
			}
		});
		unixName.addMouseTrackListener(mouseExit);
		new Label(composite, SWT.NONE);

		engineChecks = new Button[maxEngines];
		new Label(composite, SWT.NONE).setText(Messages.Engines+":"); //$NON-NLS-1$
		for(int i = 0; i < maxEngines; i++){
			engineChecks[i] = new Button(composite, SWT.CHECK);
			gd = new GridData();
			gd.widthHint = 160;
			gd.horizontalAlignment = SWT.FILL;
			engineChecks[i].setLayoutData(gd);
			if(i%2 != 0){
				new Label(composite, SWT.NONE);
				new Label(composite, SWT.NONE);
			}
//			engine[i].addListener(SWT.MouseEnter, new Listener() {
//				public void handleEvent(Event e) {
//					if(e.widget.getData() != null)
//						applyStatus(new Status(IStatus.INFO, "packageName",
//							(String)(e.widget.getData()) ) );
//				}
//			});
//			engines[i].addMouseTrackListener(mouseExit);
		}
		componentCombo.select(0);
		componentChanged();
	}

	/**
	 * Try to load component list from repository directory of the project
	 * @param project - the project to load components
	 * @throws Exception if it couldn't load component list
	 */
	public void loadComponents(IProject project) throws Exception {
		this.project = project;
		//get repos path
		String reposPath = TitanUtils.getProjectProperty(project, "reposPath"); //$NON-NLS-1$
		//load components from repos directory
		compList = new ComponentList(reposPath);
		//get the maximum number of engines that a component in the component list have
		maxEngines = compList.getMaxEngines();

		//get local component path
		localCompPath = TitanUtils.getProjectProperty(project, "projectPath") //$NON-NLS-1$
				+"local"+File.separator+"component"+File.separator; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Method called when the component selection has changed.
	 * It displays the selected component
	 */
	protected void componentChanged() {
		//get selected component
		int index = componentCombo.getSelectionIndex() > 0 ? componentCombo.getSelectionIndex() : 0;
		ComponentData cd = compList.getComponent(index);
		//enable info button if there's documentation for the component
		componentDoc = cd.getDoc();
		if(componentDoc != null)
			infoButton.setEnabled(true);
		else
			infoButton.setEnabled(false);
		//set suggested component name
		String[] nameParts = cd.getName().split("\\."); //$NON-NLS-1$
		String name = nameParts[nameParts.length-1];
		unixName.setText("local."+name); //$NON-NLS-1$
		//display the component engines
		int length = cd.getEnginesNumber();
		for(int i = 0; i < length; i++){
			engineChecks[i].setVisible(true);
			engineChecks[i].setSelection(false);
			//engineChecks[i].setData(/*TODO:*/cd.getEngineHelp(i));
			engineChecks[i].setText(cd.getEngineName(i));
		}
		for(int i = length; i < maxEngines; i++)
			engineChecks[i].setVisible(false);
	}

	/**
	 * Copy the selected component and engines from repository to application directory
	 * @return true if everything went OK, false otherwise
	 */
	public boolean copySelectedComponent() {
		try {
			//copy the selected component
			ComponentData cd = compList.getComponent(componentCombo.getSelectionIndex());
			cd.copy(localCompPath+unixName.getText());
			//copy the selected engines
			for(int i = 0; i < cd.getEnginesNumber(); i++)
				if(engineChecks[i].getSelection())
					cd.copyEngine(i);
		} catch (Exception e) {
			MessageDialog.openError(getShell(), Messages.Error, e.getMessage());
			return false;
		}

		try {
			project.refreshLocal(IResource.DEPTH_INFINITE, null);
		} catch (Exception e) {
			//do nothing... unable to refresh project tree (silent fail)
		}
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	protected void applyStatus(IStatus new_status) {
		if(new_status.getSeverity() != IStatus.INFO)
			unixNameStatus = new_status;
		applyPageStatus(new_status);
	}

	/**
	 * {@inheritDoc}
	 */
	protected IStatus greaterStatus() {
		return unixNameStatus;
	}

	/**
	 * Returns whether this page is completed
	 * @return true if the wizard could be finished, and false otherwise
	 */
	public boolean canFinish() {
		if(pageStatus.getSeverity() == IStatus.ERROR || unixName.getText().isEmpty()) //$NON-NLS-1$
			return false;
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean canFlipToNextPage() {
		return false;
	}
}